﻿namespace CatClient.Message.Internals
{
    using CatClient.Message;
    using CatClient.Message.Spi;
    using CatClient.Message.Spi.Codec;
    using CatClient.Util;
    using System;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Text;

    [Serializable]
    public abstract class AbstractMessage : IMessage
    {
        private readonly string _name;
        private readonly string _type;
        private bool _completed;
        private StringBuilder _data;
        private readonly IMessageManager _messageManager;
        private string _status = "0";

        protected AbstractMessage(string type, string name, IMessageManager messageManager = null)
        {
            this._type = type;
            this._name = name;
            this._messageManager = messageManager;
            this.TimestampInMicros = MilliSecondTimer.CurrentTimeMicros;
        }

        public void AddData(string keyValuePairs)
        {
            if (this._data == null)
            {
                this._data = new StringBuilder(keyValuePairs);
            }
            else
            {
                this._data.Append(keyValuePairs);
            }
        }

        public void AddData(string key, object value)
        {
            if (this._data == null)
            {
                this._data = new StringBuilder();
            }
            else if (this._data.Length > 0)
            {
                this._data.Append('&');
            }
            this._data.Append(key).Append('=').Append(value);
        }

        public virtual void Complete()
        {
            this.SetCompleted(true);
        }

        public bool IsCompleted() => 
            this._completed;

        public bool IsSuccess() => 
            ("0" == this.Status);

        public void SetCompleted(bool completed)
        {
            this._completed = completed;
        }

        public void SetStatus(Exception e)
        {
            this.Status = e.ToString();
        }

        public override string ToString()
        {
            ChannelBuffer buf = new ChannelBuffer(0x2000);
            new PlainTextMessageCodec().EncodeMessage(this, buf);
            buf.Reset();
            return buf.ToString();
        }

        protected long TimestampInMicros { get; private set; }

        public IMessageManager MessageManager =>
            this._messageManager;

        public string Data
        {
            get
            {
                if (this._data != null)
                {
                    return this._data.ToString();
                }
                return string.Empty;
            }
        }

        public string Name =>
            this._name;

        public string Status
        {
            get
            {
                return this._status;
            }
            set
            {
                this._status = value;
            }
        }

        public long Timestamp
        {
            get
            {
                return this.TimestampInMicros / 1000L;
            }
            set
            {
                this.TimestampInMicros = value * 1000L;
            }
        }

        public string Type =>
            this._type;
    }
}

